-- -------------------------------------------------------------------------
-- Features/Online.lua
-- Session UI Component Test
-- -------------------------------------------------------------------------

local module = {}

-- [Dependencies]
local ui = nil
local notification = nil
local features_config = nil

local function _T(text)
    if _G and _G._T then
        return _G._T(text)
    end
    return text
end

-- [Lua 5.4] <const> for function references
local pcall <const> = pcall
local type <const> = type
local ipairs <const> = ipairs
local pairs <const> = pairs
local os_time <const> = os.time
local os_clock <const> = os.clock

-- [Lua 5.4] <const> for module name
local MODULE_NAME <const> = "Online"

-- [State]
local state = {
    subtab_idx = 1,
    -- Notification toggles
    join_notify = true,
    leave_notify = true,
    modder_notify = true,
    -- Event subscriptions
    sub_join = nil,
    sub_leave = nil,
    sub_flagged = nil,
    -- Player tracking
    known_players = {},
    known_players_count = 0,
    -- Cooldown
    notify_cooldown = {},
    -- Cleanup timer
    last_cleanup = 0,
    -- Dropdown test
    dropdown_idx = 1,
    -- Test tab state
    test_inline_tab = 1,
    test_progress = 0.35,
    test_checkbox = false,
    test_checkbox_tooltip = false,  -- Separate state for "Hover for tooltip" checkbox
    test_slider = 50,
    test_combo_idx = 1,
    -- Inline toggle/color test
    test_toggle1 = false,
    test_toggle2 = true,
    test_color1 = {r=255, g=100, b=100, a=255},
    test_color2 = {r=100, g=180, b=255, a=255}
}

-- -------------------------------------------------------------------------
-- Helper Functions
-- -------------------------------------------------------------------------

local function show_notify(msg, type_str)
    if notification and notification.notify then
        notification.notify(msg, type_str)
    end
end

-- Cleanup expired cooldown entries (every 30 seconds)
local function cleanup_cooldown()
    local now = os_clock()
    if (now - state.last_cleanup) < 30 then return end
    state.last_cleanup = now

    -- Remove expired cooldown entries (older than 10 seconds)
    local expired_ids = {}
    for id, time in pairs(state.notify_cooldown) do
        if (now - time) > 10 then
            expired_ids[#expired_ids + 1] = id
        end
    end
    for i = 1, #expired_ids do
        state.notify_cooldown[expired_ids[i]] = nil
    end

    -- LRU eviction: Remove oldest entries when > 64 (use explicit counter)
    if state.known_players_count > 64 then
        -- Find and remove oldest entries (by join_time)
        local entries = {}
        for id, data in pairs(state.known_players) do
            entries[#entries + 1] = { id = id, time = data.join_time or 0 }
        end
        table.sort(entries, function(a, b) return a.time < b.time end)
        -- Remove oldest until we're at 48 (keep 75% capacity)
        local to_remove = state.known_players_count - 48
        for i = 1, to_remove do
            state.known_players[entries[i].id] = nil
            state.known_players_count = state.known_players_count - 1
        end
    end
end

-- -------------------------------------------------------------------------
-- Event Handlers
-- -------------------------------------------------------------------------

local function on_player_join(data)
    local player = data and data.player
    if not player then return end

    local name = player.name
    local id = player.id
    if not name or name == "" or name == "**Invalid**" then return end

    if not state.known_players[id] then
        state.known_players_count = state.known_players_count + 1
    end
    state.known_players[id] = { name = name, join_time = os_time() }

    if state.join_notify then
        show_notify(string.format(_T("%s is joined"), name), "Join")
    end
end

local function on_player_leave(data)
    local player = data and data.player
    if not player then return end

    local name = player.name
    local id = player.id

    if (not name or name == "" or name == "**Invalid**") and id then
        local cached = state.known_players[id]
        if cached then name = cached.name end
    end

    if state.leave_notify and name and name ~= "" then
        show_notify(string.format(_T("%s is left"), name), "Leave")
    end

    if id then
        if state.known_players[id] then
            state.known_players_count = state.known_players_count - 1
        end
        state.known_players[id] = nil
        if state.notify_cooldown[id] then
        end
        state.notify_cooldown[id] = nil
    end
end

local function on_player_flagged(data)
    local player = data and data.player
    local reason = data and data.reason
    if not player then return end

    local name = player.name
    local id = player.id

    if not name or name == "" or name == "**Invalid**" then return end

    -- Cooldown check (3 seconds)
    local now = os_clock()
    if state.notify_cooldown[id] and (now - state.notify_cooldown[id]) < 3.0 then
        return
    end
    state.notify_cooldown[id] = now

    if state.modder_notify then
        local msg = string.format(_T("Player: %s\nReason: %s"), name, tostring(reason or _T("Flagged")))
        show_notify(msg, "Modder Detection")
    end
end

-- -------------------------------------------------------------------------
-- Event Subscription
-- -------------------------------------------------------------------------

local function subscribe_events()
    if not events or not events.subscribe or not events.event then
        return false
    end

    if state.sub_join then pcall(events.unsubscribe, state.sub_join) end
    if state.sub_leave then pcall(events.unsubscribe, state.sub_leave) end
    if state.sub_flagged then pcall(events.unsubscribe, state.sub_flagged) end

    local ok1, id1 = pcall(events.subscribe, events.event.player_join, on_player_join)
    local ok2, id2 = pcall(events.subscribe, events.event.player_leave, on_player_leave)
    local ok3, id3 = pcall(events.subscribe, events.event.player_flagged, on_player_flagged)

    state.sub_join = ok1 and id1 or nil
    state.sub_leave = ok2 and id2 or nil
    state.sub_flagged = ok3 and id3 or nil

    return ok1 and ok2 and ok3
end

local function init_known_players()
    if not players or not players.list then return end

    local ok, list = pcall(players.list)
    if not ok or type(list) ~= "table" then return end

    for _, p in ipairs(list) do
        if p and p.connected and p.id and p.name then
            state.known_players[p.id] = { name = p.name, join_time = os_time() }
            state.known_players_count = state.known_players_count + 1
        end
    end
end

-- -------------------------------------------------------------------------
-- Config Save/Load Helpers
-- -------------------------------------------------------------------------

local function load_config()
    if not features_config then return end
    local saved = features_config.get_module(MODULE_NAME)
    if not saved then return end
    if saved.join_notify ~= nil then state.join_notify = saved.join_notify end
    if saved.leave_notify ~= nil then state.leave_notify = saved.leave_notify end
    if saved.modder_notify ~= nil then state.modder_notify = saved.modder_notify end
end

local function save_config()
    if not features_config then return end
    features_config.set_module(MODULE_NAME, {
        join_notify = state.join_notify,
        leave_notify = state.leave_notify,
        modder_notify = state.modder_notify
    }, true)
end

-- -------------------------------------------------------------------------
-- Module Interface
-- -------------------------------------------------------------------------

function module.init(u, _, _, _, _, _, _)
    ui = u
    notification = require("ClickUl.UI.notification")
    local ok, fc = pcall(require, "ClickUl.Config.features")
    if ok and fc then features_config = fc end
    state.known_players = {}
    state.known_players_count = 0
    state.notify_cooldown = {}
    state.last_cleanup = os_clock()
    init_known_players()
    subscribe_events()
    load_config()
end

function module.draw()
    -- Periodic cleanup
    cleanup_cooldown()

    state.subtab_idx = ui.SubTabBar({_T("Session"), _T("UI Test")}, state.subtab_idx or 1)

    if state.subtab_idx == 1 then
        ui.DualColumn(
            function()
                ui.Group(_T("Notifications"), function()
                    state.join_notify = ui.Checkbox(_T("Player Join"), state.join_notify, "Hotkey: F5 | Toggle join notifications")
                    state.leave_notify = ui.Checkbox(_T("Player Leave"), state.leave_notify, "Hotkey: F6 | Toggle leave notifications")
                    state.modder_notify = ui.Checkbox(_T("Modder Detection"), state.modder_notify, "Hotkey: F7 | Toggle modder detection alerts")
                end)
            end,
            function()
                ui.Group(_T("Dropdown Test"), function()
                    local options = {
                        _T("Option 1"), _T("Option 2"), _T("Option 3"), _T("Option 4"), _T("Option 5"),
                        _T("Option 6"), _T("Option 7"), _T("Option 8"), _T("Option 9"), _T("Option 10")
                    }
                    state.dropdown_idx = ui.Combo(_T("Select"), state.dropdown_idx, options, "Arrow Keys + Enter | Select from dropdown list")
                end)
            end
        )

    -- UI Test Tab
    elseif state.subtab_idx == 2 then
        ui.DualColumn(
            function()
                -- InlineTabBar Test
                ui.Group(_T("InlineTabBar"), function()
                    state.test_inline_tab = ui.InlineTabBar({_T("Basic"), _T("Advanced"), _T("Debug")}, state.test_inline_tab)

                    if state.test_inline_tab == 1 then
                        -- Basic: 2 simple options
                        ui.Button(_T("Simple Action"), "Shortcut: Ctrl+E | Execute simple action")
                        state.test_checkbox = ui.Checkbox(_T("Enable Feature"), state.test_checkbox, "Shortcut: Ctrl+F | Toggle this feature on/off", _T("Toggle this feature on/off"))

                    elseif state.test_inline_tab == 2 then
                        -- Advanced: 5 options with variety
                        ui.Button(_T("Execute Command"), "Shortcut: Ctrl+X | Run advanced command")
                        state.test_slider = ui.Slider(_T("Power") .. "##adv", state.test_slider, 0, 100, 5, "Mouse Drag | Adjust power level 0-100", _T("Adjust power level (0-100)"))
                        state.test_combo_idx = ui.Combo(_T("Mode") .. "##adv", state.test_combo_idx, {_T("Normal", _T("Select operation mode")), _T("Fast"), _T("Turbo"), _T("Ultra")}, "Click to expand | Select operation mode")
                        ui.Checkbox(_T("Auto-save"), false, _T("Automatically save changes"))
                        ui.Button(_T("Apply Settings"), "Shortcut: Ctrl+S | Apply all settings")

                    else
                        -- Debug: 6+ options for debugging
                        ui.Button(_T("Print Debug Info"), "Shortcut: F12 | Output debug info to console")
                        ui.Button(_T("Clear Cache"), "Shortcut: Ctrl+Del | Clear all cached data")
                        ui.Button(_T("Reset State"), "Shortcut: Ctrl+R | Reset UI state")
                        ui.Separator(_T("Logging"))
                        ui.Checkbox(_T("Verbose Mode"), false, _T("Enable verbose logging"))
                        ui.Checkbox(_T("Log to File"), false, _T("Write logs to file"))
                        ui.Slider(_T("Log Level") .. "##dbg", 3, 1, 5, 1, _T("1=Error, 2=Warn, 3=Info, 4=Debug, 5=Trace"))
                    end
                end)

                -- Separator Test
                ui.Group(_T("Separator"), function()
                    ui.Button(_T("Button Above"))
                    ui.Separator()
                    ui.Button(_T("Button Below"))
                    ui.Separator(_T("Section Title"))
                    ui.Button(_T("After Section"))
                end)

                -- Row Layout Test
                ui.Group(_T("Row Layout"), function()
                    -- 2 buttons in a row
                    ui.Row({
                        function() ui.Button(_T("Left")) end,
                        function() ui.Button(_T("Right")) end
                    })

                    -- 3 buttons in a row
                    ui.Row({
                        function() ui.Button(_T("A")) end,
                        function() ui.Button(_T("B")) end,
                        function() ui.Button(_T("C")) end
                    })

                    -- Simplified ButtonRow
                    local clicked = ui.ButtonRow({_T("Save"), _T("Load"), _T("Reset"), _T("Exit")})
                    if clicked then
                        show_notify(string.format(_T("Clicked button %s"), clicked), "Success")
                    end
                end)

                -- Text Truncation Test
                ui.Group(_T("Text Truncation"), function()
                    -- Long text example
                    local long_text = _T("This is a very long text that should be truncated with ellipsis...")
                    ui.Button(ui.truncate_text(long_text, 14, ui.s(180)))

                    -- Player name example
                    local name = "SuperLongPlayerNameThatWontFit"
                    ui.Button(ui.truncate_text(name, 14, ui.s(120)))

                    -- Row with truncated buttons
                    ui.Row({
                        function()
                            ui.Button(ui.truncate_text(_T("VeryLongButtonLabel"), 14, ui.s(80)))
                        end,
                        function()
                            ui.Button(ui.truncate_text(_T("AnotherLongText"), 14, ui.s(80)))
                        end
                    })
                end)

                -- More Tooltip Tests
                ui.Group(_T("Tooltip Examples"), function()
                    -- Combo with tooltip
                    state.test_combo_idx = ui.Combo(_T("Select Item"), state.test_combo_idx, {_T("Apple", _T("Select your favorite fruit from the dropdown list")), _T("Banana"), _T("Cherry"), _T("Date"), _T("Elderberry")})

                    -- Multiple buttons with different tooltips
                    if ui.Button(_T("Short Tip"), _T("Short")) then end

                    if ui.Button(_T("Long Tooltip Text"), _T("This is a much longer tooltip that demonstrates how the tooltip system handles extended text content and positions itself on screen")) then end

                    if ui.Button(_T("Multi-line Tip"), _T("Line 1: First line\nLine 2: Second line\nLine 3: Third line")) then end
                end)
            end,
            function()
                -- ProgressBar Test
                ui.Group(_T("ProgressBar"), function()
                    ui.ProgressBar(_T("Download"), state.test_progress)

                    ui.ProgressBar(_T("Health"), 0.75, "Tag Green")

                    ui.ProgressBar(_T("Armor"), 0.25, "Tag Blue")

                    -- Animate progress
                    state.test_progress = state.test_progress + 0.002
                    if state.test_progress > 1 then state.test_progress = 0 end
                end)

                -- Tooltip Test
                ui.Group(_T("Interactive Tooltip"), function()
                    state.test_checkbox_tooltip = ui.Checkbox(_T("Hover for tooltip"), state.test_checkbox_tooltip, _T("This checkbox does something important!\nHover delay is configurable in Settings."))

                    state.test_slider = ui.Slider(_T("Slider") .. "##test", state.test_slider, 0, 100, 1)

                    if ui.Button(_T("Test Notification"), _T("Click to show a success notification")) then
                        show_notify(_T("Button clicked!"), "Success")
                    end

                    if ui.Button(_T("Test Warning"), _T("Click to show a warning notification")) then
                        show_notify(_T("This is a warning!"), "Warning")
                    end
                end)

                -- Inline Toggle & Color Test
                ui.Group(_T("Inline Controls"), function()
                    -- Two side-by-side toggles
                    ui.Row({
                        function()
                            state.test_toggle1 = ui.Checkbox(_T("Toggle A"), state.test_toggle1)
                        end,
                        function()
                            state.test_toggle2 = ui.Checkbox(_T("Toggle B"), state.test_toggle2, _T("Two toggles in a row"))
                        end
                    })

                    -- Two side-by-side color pickers
                    ui.Row({
                        function()
                            ui.ColorPicker(_T("Color A"), state, "test_color1")
                        end,
                        function()
                            ui.ColorPicker(_T("Color B"), state, "test_color2")
                        end
                    })
                end)

                -- Collapsible Test
                ui.Collapsible(_T("Collapsible Basic"), function()
                    ui.Text(_T("This content is collapsible!"))
                    ui.Button(_T("Hidden Button"), _T("This button is inside a collapsible section"))
                    state.test_checkbox = ui.Checkbox(_T("Hidden Option"), state.test_checkbox)
                end)

                ui.Collapsible(_T("Collapsible Advanced"), function()
                    state.test_slider = ui.Slider(_T("Hidden Slider"), state.test_slider, 0, 100, 1)
                    state.test_combo_idx = ui.Combo(_T("Hidden Combo"), state.test_combo_idx, {_T("Option A"), _T("Option B"), _T("Option C")})
                    ui.Row({
                        function() ui.Button(_T("Action 1")) end,
                        function() ui.Button(_T("Action 2")) end
                    })
                end, nil, true)  -- default expanded

                ui.Collapsible(_T("Nested Collapsible"), function()
                    ui.Text(_T("Outer content"))
                    ui.Collapsible(_T("Inner Section 1"), function()
                        ui.Button(_T("Inner Button 1"))
                        ui.Checkbox(_T("Inner Check 1"), false)
                    end)
                    ui.Collapsible(_T("Inner Section 2"), function()
                        ui.Button(_T("Inner Button 2"))
                        ui.Slider(_T("Inner Slider"), 50, 0, 100, 1)
                    end)
                end)
            end
        )
    end
end

function module.on_menu_close()
    save_config()
end

-- Cleanup function to unsubscribe events (called on unload)
function module.unload()
    if events and events.unsubscribe then
        if state.sub_join then pcall(events.unsubscribe, state.sub_join); state.sub_join = nil end
        if state.sub_leave then pcall(events.unsubscribe, state.sub_leave); state.sub_leave = nil end
        if state.sub_flagged then pcall(events.unsubscribe, state.sub_flagged); state.sub_flagged = nil end
    end
    state.known_players = {}
    state.known_players_count = 0
    state.notify_cooldown = {}
end

return module
